package com.anivia.common.web.config.dataScope;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.json.JSONUtil;
import com.anivia.common.web.model.vo.DataScopeVO;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.*;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.select.PlainSelect;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 数据权限处理器
 *
 * @author wangj
 */
@Slf4j
public class MyDataPermissionHandler {
    /**
     * 获取数据权限 SQL片段
     */
    @SneakyThrows(Exception.class)
    public Expression getSqlSegment(PlainSelect plainSelect, String whereSegment) {
        Expression where = plainSelect.getWhere();
        if (where == null) {
            where = new HexValue("1 = 1");
        }
        DataScopeVO dataScopeVO = DataScopeContext.get();
        log.info("数据权限参数: {}", JSONUtil.toJsonStr(dataScopeVO));
        if (dataScopeVO.isOpenScope()) {
            if (dataScopeVO.isHasDataScope()) {
                // 有权限，拼接过滤条件
                return buildWhere(where, plainSelect, dataScopeVO.getDataScopeItem());
            } else {
                // 无权限
                return new HexValue("1 = 2");
            }
        } else {
            return where;
        }
    }

    /**
     * 构建where条件
     */
    private Expression buildWhere(Expression where, PlainSelect plainSelect, Map<String, Set<Integer>> params) {
        Table fromItem = (Table) plainSelect.getFromItem();
        // 有别名用别名，无别名用表名，防止字段冲突报错
        Alias fromItemAlias = fromItem.getAlias();
        String mainTableName = fromItemAlias == null ? fromItem.getName() : fromItemAlias.getName();

        Expression expression = new HexValue("1 = 2");
        for (Map.Entry<String, Set<Integer>> entry : params.entrySet()) {
            Set<Integer> values = entry.getValue();
            log.debug("字段[{}]的值为:{}!", entry.getKey(), JSONUtil.toJsonStr(values));
            // 开启数据权限，但是条件字段没有值，则跳过
            if (CollUtil.isEmpty(values)) {
                continue;
            }
            // 如果条件只有一个值，使用 =
            if (values.size() == 1) {
                EqualsTo equalsTo = new EqualsTo();
                equalsTo.setLeftExpression(new Column(mainTableName + "." + entry.getKey()));
                equalsTo.setRightExpression(handlerValue(values.iterator().next()));
                expression = new OrExpression(expression, equalsTo);
                continue;
            }
            // 如果条件有多个值，则使用 in
            if (values.size() > 1) {
                InExpression inExpression = new InExpression();
                inExpression.setLeftExpression(new Column(mainTableName + "." + entry.getKey()));
                List<Expression> expressions = new ArrayList<>();
                for (Integer deptId : entry.getValue()) {
                    expressions.add(handlerValue(deptId));
                }
                ExpressionList expressionList = new ExpressionList();
                expressionList.setExpressions(expressions);
                inExpression.setRightExpression(expressionList);
//                inExpression.setRightItemsList(expressionList);
                expression = new OrExpression(expression, inExpression);
            }
        }
        where = new AndExpression(where, new Parenthesis(expression));
        return where;
    }

    private Expression handlerValue(Object value) {
        if (value instanceof Integer || value instanceof Long) {
            return new LongValue(Convert.toStr(value));
        }
        return new StringValue(Convert.toStr(value));
    }
}